#include "texture.h"



namespace rendersystem {
Texture::Texture(std::string name, GLenum target, TexType type, GLuint zOffset) : mTexId(0), mName(name), mTarget(target), mType(type), mZOffset(zOffset)
{

    QImage img(name.c_str());
    std::cerr << name << " : " << img.width() << "x" << img.height() << " - " << img.depth() << "bpp" << std::endl;

    int bpp = (img.depth() == 32) ? GL_RGBA : GL_RGB;
    int format = (img.depth() == 32) ? GL_BGRA : GL_BGR;

    initGL(bpp, img.width(), img.height(), format, GL_UNSIGNED_BYTE, img.bits() );
}

Texture::Texture (unsigned char color[3]){
    initGL(GL_RGB, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, color);
}

void Texture::initGL(int bytesperpixel, int width, int height, int format, int type, void* data)
{
    mBytesperpixel =bytesperpixel;
    mFormat=format;
    mData=data;
    mType2=type;

    glAssert(glGenTextures(1, &mTexId));
    glAssert(glBindTexture(mTarget, mTexId));
    glAssert(glTexImage2D(mTarget, 0, bytesperpixel, width, height, 0, format, type, data));
    glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
    glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
    glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
    glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
}

void Texture::cubeInitGL(int bytesperpixel, int width, int height, int format, int type, void** data)
{
    mBytesperpixel =bytesperpixel;
    mFormat=format;
    mData=data;
    mType2=type;

    glAssert(glGenTextures(1, &mTexId));
    glAssert(glBindTexture(mTarget, mTexId));
    glAssert(glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS));
    glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[0]);
    glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[1]);
    glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[2]);
    glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[3]);
    glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[4]);
    glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data[5]);

    glAssert (glBindTexture (mTarget, mTexId));

    glAssert(glTexParameteri (mTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
    glAssert(glTexParameteri (mTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    glAssert( glGenerateMipmap(mTarget) );

}

void Texture::useMipMap(GLenum minFliter, GLenum magFilter)
{
    glAssert(glBindTexture(mTarget, mTexId));
    glAssert(glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, magFilter));
    glAssert(glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, minFliter));
    glAssert(glGenerateMipmap(mTarget));
}

void Texture::setFilter(GLenum minFliter, GLenum magFilter)
{
    glAssert(glBindTexture(mTarget, mTexId));
    glAssert(glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, magFilter));
    glAssert(glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, minFliter));
}
void Texture::setClamp(GLenum warpS, GLenum warpT)
{
    glAssert(glBindTexture(mTarget, mTexId));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, warpS);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, warpT);
}


void Texture::bind(int unit)
{
    GLenum texUnit = GL_TEXTURE0+unit;
    glAssert(glActiveTexture(texUnit));
//    glAssert(glEnable(mTarget)); // INUTILE en OpenGL 3.x
    glAssert(glBindTexture(mTarget, mTexId));
}

void Texture::deleteGL()
{
    glDeleteTextures(1, &mTexId);
}

void Texture::setSize(int width, int height){
    // verification des dimensions :
    int MAX_SIZE;
#ifdef __APPLE__
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MAX_SIZE);
#else
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MAX_SIZE);
#endif
    if ((width > 0) && (width <= MAX_SIZE) && (height > 0) && (height <= MAX_SIZE)) {
        glAssert(glBindTexture(mTarget, mTexId));
        glAssert(glTexImage2D(mTarget, 0, mBytesperpixel, width, height, 0, mFormat, mType, mData));
    } else {
        std::cerr << "Error : invalid size (" << width << " , " << height << "): maximum size supported = " << MAX_SIZE << " (Texture not resized)" << std::endl;
    }
}

}
